package http

import io.vertx.core.Vertx
import io.vertx.kotlin.core.http.*
import io.vertx.kotlin.core.net.*
import io.vertx.ext.web.Router
import io.vertx.ext.web.handler.CookieHandler
import io.vertx.ext.web.handler.SessionHandler
import io.vertx.ext.web.handler.StaticHandler
import io.vertx.ext.web.handler.sockjs.BridgeOptions
import io.vertx.ext.web.handler.sockjs.PermittedOptions
import io.vertx.ext.web.handler.sockjs.SockJSHandler
import io.vertx.ext.web.sstore.LocalSessionStore
import io.vertx.kotlin.ext.web.handler.sockjs.*

class ChatServer : io.vertx.core.AbstractVerticle()  {
  override fun start() {

    var router = Router.router(vertx)
    router.route().handler(CookieHandler.create())
    router.route().handler(SessionHandler.create(LocalSessionStore.create(vertx)))

    // Allow events for the designated addresses in/out of the event bus bridge
    var opts = BridgeOptions(
      inboundPermitteds = listOf(PermittedOptions(
        address = "chat.to.server")),
      outboundPermitteds = listOf(PermittedOptions(
        address = "chat.to.client")))

    // Create the event bus bridge and add it to the router.
    var ebHandler = SockJSHandler.create(vertx).bridge(opts)
    router.route("/eventbus/*").handler(ebHandler)

    // Create a router endpoint for the static content.
    router.route().handler(StaticHandler.create("webroot/chat"))

    // Start the web server and tell it to use the router to handle requests.
    val hop = HttpServerOptions(
      ssl=true,
      keyStoreOptions = JksOptions(
              path = "server-keystore.jks",
              password = "wibble")
    )
    vertx.createHttpServer(hop)
      .requestHandler({ router.accept(it) }).listen(8080)
    println("https server listen at https://localhost:8080")

    var eb = vertx.eventBus()

    // Register to listen for messages coming IN to the server
    eb.consumer<Any>("chat.to.server").handler({ message ->
      // Create a timestamp string
      var timestamp = java.text.DateFormat.getDateTimeInstance(java.text.DateFormat.SHORT, java.text.DateFormat.MEDIUM).format(java.util.Date.from(java.time.Instant.now()))
      // Send the message back out to all clients with the timestamp prepended.
      eb.publish("chat.to.client", "${timestamp}: ${message.body()}")
    })

  }
}

fun main(args: Array<String>) {
  val vertx = Vertx.vertx()
  vertx.deployVerticle(ChatServer())
}
